home *** CD-ROM | disk | FTP | other *** search
/ PsL Monthly 1994 January / PSL Monthly Shareware CD-ROM (Public Software Library) (January 1994).iso / games / dos / board / backgam.com / BKG.C < prev    next >
Encoding:
C/C++ Source or Header  |  1979-11-30  |  32.5 KB  |  1,268 lines

  1. /*P*/
  2. /****************************************************************/
  3. /*                                */
  4. /* backgammon                            */
  5. /*                                */
  6. /* This is a program to play backgammon with the user. The    */
  7. /* board is displayed from a "top view", and has numbers    */
  8. /* surrounding the points. The system will automatically roll    */
  9. /* the dice for you, and makes its own moves according to some    */
  10. /* simple evaluations.                        */
  11. /*                                */
  12. /* It is assumed that you know how to play backgammon. This    */
  13. /* program will play either as white, or as black; this is an    */
  14. /* option you select. Unlike some variations of backgammon,    */
  15. /* each game is played in the same direction (according to the    */
  16. /* rules, this is correct - some people reverse on every-other    */
  17. /* game). In order to run the program, you just type in "bkg".    */
  18. /* A keystroke sets the internal random number generation. You    */
  19. /* specify either white or black at this time.            */
  20. /*                                */
  21. /* The program prompts you to "Return to roll: ". Just pressing    */
  22. /* a return character rolls the dice, and you may then make a    */
  23. /* move. Moves are specified by a simple method - you type the    */
  24. /* number of the point to move from, a slash, and the number    */
  25. /* of points to move. For example, if you rolled a 4 and a 6,    */
  26. /* and you have players on points 12 and 7, you might play    */
  27. /* something like "7/6 12/4", or "12/6 7/4", or even "12/6/4"    */
  28. /* or "7/4/6", etc... Note that you must obey the rules - no    */
  29. /* point that is occupied by >= 2 of the opponents men can be    */
  30. /* landed on, etc.                        */
  31. /*                                */
  32. /* When you or the opponent are "hit", a man is placed on the    */
  33. /* bar in the middle. You can move off of the bar by using a    */
  34. /* "b" in place of the source point, like: "b/3 13/5". You can    */
  35. /* also use the numbers 0 and 25 for the bar, if you like.    */
  36. /*                                */
  37. /* Doubling is supported. The box on the bar with a '1' in it    */
  38. /* is the doubling cube. When you want to double, wait for the    */
  39. /* "Return to roll: " message, then type "double" or "d". Also,    */
  40. /* the computer may double you, in which case you need to    */
  41. /* decide whether or not to accept. Again, familiarity with the    */
  42. /* rules of the game will help on this...            */
  43. /*                                */
  44. /* Lastly, you can type "quit" in place of "double" to get out    */
  45. /* quick when the boss shows up.                */
  46. /*                                */
  47. /* Author:    Bill Mahoney                    */
  48. /*        1819 North 66th Street                */
  49. /*        Omaha, Nebraska  68104                */
  50. /*        (402) 554-0312                    */
  51. /*                                */
  52. /* Date:    Misc. 1986                    */
  53. /*                                */
  54. /* Copyright:    1986, Mahoney                    */
  55. /*                                */
  56. /****************************************************************/
  57.  
  58. #define        MAIN
  59. #include    <stdio.h>
  60. #include    "bkg.h"
  61.  
  62. /*P*/
  63. /****************************************************************/
  64. /*                                */
  65. /* main                                */
  66. /*                                */
  67. /* There are sume undocumented features here. Ok, ok, so now    */
  68. /* they aren't undocumented anymore! For testing, you can give    */
  69. /* a "-g" option, and play many many games. This is used to    */
  70. /* test out new evaluation strategy against old. A "-d" lets    */
  71. /* you use "debug" instead of "double" or "quit". See that    */
  72. /* section for debugging commands.                */
  73. /*                                */
  74. /****************************************************************/
  75.  
  76. main( ac, av )
  77.  
  78. int    ac;
  79. char    *av[];
  80.  
  81.     {
  82.  
  83.     char    ch;
  84.     int    i, j, games, played, white, black;
  85.     int    c_white, c_black, side;
  86.     int    value, on_board;
  87.  
  88.     games = 0;
  89.     white = black = 0;
  90.     k10 = FALSE;
  91.  
  92.     for( i = 1; i < ac; i++ )
  93.         if ( av[ i ][ 0 ] == '-' )
  94.             switch( toupper( av[ i ][ 1 ] ) )
  95.                 {
  96.  
  97.                 case 'D':    debug++;
  98.                         break;
  99.  
  100.                 case 'G':    sscanf( av[ ++i ], "%d", &games );
  101.                         break;
  102.  
  103.                 case 'R':    r_test++;
  104.                         break;
  105.  
  106.                 default:    printf( "Usage: bkg\n" );
  107.                         exit( 0 );
  108.                         break;
  109.  
  110.                 } /* end args */
  111.         else
  112.             {
  113.             printf( "Usage: bkg\n" );
  114.             exit( 0 );
  115.             }
  116.  
  117.     /* The BDS compiler on the Kaypro does not support initialized    */
  118.     /* arrays, so we have to do it ourselves here. This is a tbl    */
  119.     /* for probability of being able to move <subscript> points    */
  120.     /* based on the possible 36 combinations.            */
  121.  
  122.     prob[ 1 ] = 11;    prob[ 2 ] = 12;    prob[ 3 ] = 13;    prob[ 4 ] = 14;
  123.     prob[ 5 ] = 15;    prob[ 6 ] = 16;    prob[ 7 ] = 6;    prob[ 8 ] = 7;
  124.     prob[ 9 ] = 5;    prob[ 10 ] = 3;    prob[ 11 ] = 2;    prob[ 12 ] = 3;
  125.     prob[ 13 ] = 0;    prob[ 14 ] = 0;    prob[ 15 ] = 1;    prob[ 16 ] = 1;
  126.     prob[ 17 ] = 0;    prob[ 18 ] = 1;    prob[ 19 ] = 0;    prob[ 20 ] = 1;
  127.     prob[ 21 ] = 0;    prob[ 22 ] = 0;    prob[ 23 ] = 0;    prob[ 24 ] = 1;
  128.  
  129.     if ( ! games )
  130.         {
  131.  
  132.         puts( "\nBackgammon, By Bill Mahoney" );
  133.         srand1( "\nPress any Key: " );
  134.         if ( getchar() != '\n' )
  135.             putchar( '\n' );
  136.  
  137.         printf( "Will you be playing white, or black? " );
  138.         do    {
  139.             ch = toupper( raw_keyboard() );
  140.             } while ( ( ch != 'B' ) &&
  141.                   ( ch != 'W' ) );
  142.  
  143.         if ( ch == 'W' )
  144.             {
  145.             puts( "White\n" );
  146.             side = TRUE;
  147.             c_black = TRUE;
  148.             c_white = FALSE;
  149.             }
  150.         else
  151.             {
  152.             puts( "Black\n" );
  153.             side = FALSE;
  154.             c_white = TRUE;
  155.             c_black = FALSE;
  156.             }
  157.         }
  158.     else
  159.         {
  160.         srand( games );
  161.         side = FALSE;
  162.         c_white = c_black = TRUE;
  163.         }
  164.  
  165.     for( i = 0; i < SIZE; i++ )
  166.         board[ i ][ BLACK ] = board[ i ][ WHITE ] = board[ i ][ 2 ] = 0;
  167.  
  168.     played = 0;
  169.  
  170.     do    {
  171.  
  172.         /* Play a game. The play routine returns an    */
  173.         /* indication of just who it was that won.    */
  174.  
  175.         if ( play( c_white, c_black, white, black, side, &value, played ) )
  176.             {
  177.  
  178.             /* A "true" return is a win for black.    */
  179.             /* But it may be by way of a "quit" or    */
  180.             /* a double, so check to see if all    */
  181.             /* his men are off.            */
  182.  
  183.             for( on_board = 0, i = B_BAR; i < 25; i++ )
  184.                 on_board += board[ i ][ BLACK ];
  185.  
  186.             for( i = W_BAR; i > 18; i-- )
  187.                 if ( board[ i ][ WHITE ] )
  188.                     break;
  189.  
  190.             /* Check for the "odd" types of wins.    */
  191.  
  192.             if ( ( i > 18     ) &&
  193.                  ( ! on_board ) )
  194.                 {
  195.                 black += ( 3 * value );
  196.                 write_at( 23, 0, "Black wins a backgammon! Another game? ", TEXT_COLOR );
  197.                 }
  198.             else
  199.                 {
  200.  
  201.                 for( j = 0; i; i-- )
  202.                     j += board[ i ][ WHITE ];
  203.  
  204.                 if ( ( j == 15    ) &&
  205.                      ( ! on_board ) )
  206.                     {
  207.                     black += ( 2 * value );
  208.                     write_at( 23, 0, "Black wins a gammon! Another game? ", TEXT_COLOR );
  209.                     }
  210.                 else
  211.                     {
  212.                     black += value;
  213.                     write_at( 23, 0, "Black wins. Another game? ", TEXT_COLOR );
  214.                     }
  215.  
  216.                 } /* not a backgammon */
  217.  
  218.             } /* black wins */
  219.  
  220.         else
  221.             {
  222.  
  223.             for( on_board = 0, i = W_BAR; i; i-- )
  224.                 on_board += board[ i ][ WHITE ];
  225.  
  226.             for( i = B_BAR; i < 7; i++ )
  227.                 if ( board[ i ][ BLACK ] )
  228.                     break;
  229.  
  230.             /* Again, check for "odd" wins        */
  231.  
  232.             if ( ( i < 7      ) &&
  233.                  ( ! on_board ) )
  234.                 {
  235.                 white += ( 3 * value );
  236.                 write_at( 23, 0, "White wins a backgammon! Another game? ", TEXT_COLOR );
  237.                 }
  238.             else
  239.                 {
  240.  
  241.                 for( j = 0; i < 25; i++ )
  242.                     j += board[ i ][ BLACK ];
  243.  
  244.                 if ( ( j == 15    ) &&
  245.                      ( ! on_board ) )
  246.                     {
  247.                     white += ( 2 * value );
  248.                     write_at( 23, 0, "White wins a gammon! Another game? ", TEXT_COLOR );
  249.                     }
  250.                 else
  251.                     {
  252.                     white += value;
  253.                     write_at( 23, 0, "White wins. Another game? ", TEXT_COLOR );
  254.                     }
  255.  
  256.                 } /* not a backgammon */
  257.  
  258.             } /* white wins */
  259.  
  260.         played++;
  261.  
  262.         /* Keep on doing more games until we    */
  263.         /* use up the play limit, or the guy    */
  264.         /* has had enough laughter for today.    */
  265.  
  266.         } while ( ( ( games ) && ( games != played )    ) ||
  267.               ( toupper( raw_keyboard() ) == 'Y'    ) );
  268.  
  269.     clear();
  270.     printf( "Played %d game(s), white wins %d, black wins %d\n", played, white, black );
  271.  
  272.     } /* main */
  273.  
  274. /*P*/
  275. /****************************************************************/
  276. /*                                */
  277. /* play                                */
  278. /*                                */
  279. /* This function will take turns allowing each player to make a    */
  280. /* move. Since the computer can play either side, or both, we    */
  281. /* check when it is a players turn to move, and either call the    */
  282. /* "human type" parser, or the computer move generator. If the    */
  283. /* latter is the case, then the move generator will give us    */
  284. /* back a string in the same format as if a human typed it - or    */
  285. /* something like "4/3 5/6", whatever. We then pass this on to    */
  286. /* the parser routine.                        */
  287. /*                                */
  288. /* After each move, we scan the board to make sure that we can    */
  289. /* still play. If not, then somebody one, and we're outa here.    */
  290. /*                                */
  291. /****************************************************************/
  292.  
  293. play( c_white, c_black, w_wins, b_wins, side, value, played )
  294.  
  295. int    c_white, c_black, w_wins, b_wins, side, *value, played;
  296.  
  297.     {
  298.  
  299.     char    temp[ 80 ], line[ 80 ], ch;
  300.     int    i, j, temp1, temp2, b_count, w_count;
  301.     int    die_1, die_2, owned, winner;
  302.     int    biggest, column, first_play;
  303.  
  304.     /* Put up the board, put the    */
  305.     /* double cube on it, then go.    */
  306.  
  307.     draw( side );
  308.     show_cube( NOBODY, 1, side );
  309.     *value = 1;
  310.     winner = owned = NOBODY;
  311.     first_play = TRUE;
  312.  
  313.     /* re-initialize the board, in    */
  314.     /* case we are playing game #2    */
  315.  
  316.     for( i = 0; i < 26; i++ )
  317.         board[ i ][ WHITE ] = board[ i ][ BLACK ] = board[ i ][ 2 ] = 0;
  318.  
  319.     /* initialize the pieces on it.    */
  320.  
  321.     for( i = 0; i < 5; i++ )
  322.         {
  323.  
  324.         move_piece( -1, 6, WHITE, side );
  325.         if ( i < 3 )
  326.             move_piece( -1, 8, WHITE, side );
  327.         move_piece( -1, 13, WHITE, side );
  328.         if ( i < 2 )
  329.             move_piece( -1, 24, WHITE, side );
  330.  
  331.         if ( i < 2 )
  332.             move_piece( -1, 1, BLACK, side );
  333.         move_piece( -1, 12, BLACK, side );
  334.         if ( i < 3 )
  335.             move_piece( -1, 17, BLACK, side );
  336.         move_piece( -1, 19, BLACK, side );
  337.  
  338.         }
  339.  
  340.     /* While testing, we keep tabs on how    */
  341.     /* we're doing with b_eval vs w_eval    */
  342.  
  343.     if ( played )
  344.         {
  345.         sprintf( temp, "Played %d games, white wins %d, black wins %d.", played, w_wins, b_wins );
  346.         write_at( X_PROMPT + 3, Y_PROMPT, temp, TEXT_COLOR );
  347.         }
  348.  
  349.     /* decide who starts. This is different    */
  350.     /* than a regular roll, because each    */
  351.     /* player rolls one dice, and whatever    */
  352.     /* numbers are up, we use.        */
  353.  
  354.     do    {
  355.  
  356.         for( i = 0; i <= 25; i++ )
  357.             show_die( 1, ( die_1 = ( rand() % 6 ) + 1 ) );
  358.         sprintf( temp, "White rolls a %d.", die_1 );
  359.         write_at( X_INFO, Y_INFO, temp, TEXT_COLOR );
  360.  
  361.         for( i = 0; i <= 25; i++ )
  362.             show_die( 0, ( die_2 = ( rand() % 6 ) + 1 ) );
  363.         sprintf( temp, "Black rolls a %d.", die_2 );
  364.         write_at( X_INFO + 1, Y_INFO, temp, TEXT_COLOR );
  365.  
  366.         } while ( die_1 == die_2 );
  367.  
  368.     /* who won? let the user know    */
  369.  
  370.     if ( die_1 > die_2 )
  371.         {
  372.         me = WHITE;
  373.         sprintf( temp, "%cWhite starts with a %d, %d", CTEOL, die_1, die_2 );
  374.         write_at( X_INFO, Y_INFO, temp, TEXT_COLOR );
  375.         column = strlen( temp );
  376.         }
  377.     else
  378.         {
  379.         me = BLACK;
  380.         sprintf( temp, "%cBlack starts with a %d, %d", CTEOL, die_1, die_2 );
  381.         write_at( X_INFO + 1, Y_INFO, temp, TEXT_COLOR );
  382.         column = strlen( temp );
  383.         }
  384.  
  385.     /* play until someone wins the game */
  386.  
  387.     while( TRUE )
  388.         {
  389.  
  390.         /* Play each person in turn.    */
  391.  
  392.         if ( me == BLACK )
  393.             {
  394.  
  395.             /* Just because it is his turn    */
  396.             /* does not always mean he can    */
  397.             /* take it...            */
  398.  
  399.             if ( can_move( BLACK ) )
  400.                 {
  401.  
  402.                 if ( ! first_play )
  403.                     {
  404.  
  405.                     if ( c_black )
  406.                         {
  407.  
  408.                         /* Should we double? Check it.    */
  409.  
  410.                         get_pre_command( BLACK, line, owned, *value );
  411.                         if ( ! pre_command( line, &owned, value, side, me, &winner, &die_1, &die_2, c_black, c_white ) )
  412.                             exit( printf( "%cplay: panic: pre_command is %s\n", 0x07, line ) );
  413.                         }
  414.                     else
  415.                         do    {
  416.  
  417.                             /* Those damn humans are playing again.    */
  418.                             /* I wore out this code - I always play    */
  419.                             /* black.                */
  420.  
  421.                             char_at( X_INFO + 2, Y_INFO, CTEOL, TEXT_COLOR );
  422.                             write_at( X_INFO + 2, Y_INFO, "Return to roll: ", TEXT_COLOR );
  423.                             gets( line, 79 );
  424.  
  425.                             } while ( ! pre_command( line, &owned, value, side, me, &winner,
  426.                                          &die_1, &die_2, c_black, c_white ) );
  427.  
  428.                     if ( winner != NOBODY )
  429.                         return( winner );
  430.  
  431.                     roll( &die_1, &die_2, &column );
  432.                     if ( die_1 == die_2 )
  433.                         sprintf( temp, "%cBlack rolls double %d's", CTEOL, die_1 );
  434.                     else
  435.                         sprintf( temp, "%cBlack rolls a %d and a %d", CTEOL, die_1, die_2 );
  436.                     write_at( X_INFO + 1, Y_INFO, temp, TEXT_COLOR );
  437.  
  438.                     }
  439.  
  440.                 /* We generate a computer move, so we    */
  441.                 /* can see how many moves are allowed.    */
  442.                 /* You must make as many as you can, no    */
  443.                 /* matter what trouble it causes.    */
  444.  
  445.                 b_movegen( die_1, die_2, FALSE, &biggest, line, FALSE );
  446.  
  447.                 if ( biggest )
  448.                     {
  449.  
  450.                     if ( c_black )
  451.                         {
  452.  
  453.                         if ( first_play )
  454.                             first( die_1, die_2, BLACK, line );
  455.                         else
  456.                             b_movegen( die_1, die_2, TRUE, &biggest, line, FALSE );
  457.  
  458.                         sprintf( temp, " and moves %s", line );
  459.                         write_at( X_INFO + 1, column, temp, TEXT_COLOR );
  460.                         if ( ! handle_command( die_1, die_2, line, biggest, side ) )
  461.                             exit( printf( "%cplay: panic: computer move %s\n", 0x07, line ) );
  462.  
  463.                         } /* computer move */
  464.                     else
  465.                         do    {
  466.  
  467.                             char_at( X_INFO + 2, Y_INFO, CTEOL, TEXT_COLOR );
  468.                             write_at( X_INFO + 2, Y_INFO, "Your move: ", TEXT_COLOR );
  469.                             gets( line, 79 );
  470.  
  471.                             } while ( ! handle_command( die_1, die_2, line, biggest, side ) );
  472.  
  473.                     } /* can move */
  474.                 else
  475.                     write_at( X_INFO + 1, column, " and can not move.", ALERT_COLOR );
  476.  
  477.                 } /* can move */
  478.             else
  479.                 {
  480.                 char_at( X_INFO + 1, Y_INFO, CTEOL, TEXT_COLOR );
  481.                 write_at( X_INFO + 1, Y_INFO, "Black can not play.", ALERT_COLOR );
  482.                 }
  483.  
  484.             } /* black */
  485.         else
  486.             {
  487.  
  488.             /* This section is exactly the    */
  489.             /* same, but it handles white.    */
  490.  
  491.             if ( can_move( WHITE ) )
  492.                 {
  493.  
  494.                 if ( ! first_play )
  495.                     {
  496.  
  497.                     if ( c_white )
  498.                         {
  499.                         get_pre_command( WHITE, line, owned, *value );
  500.                         if ( ! pre_command( line, &owned, value, side, me, &winner, &die_1, &die_2, c_black, c_white ) )
  501.                             exit( printf( "%cplay: panic: pre_command is %s\n", 0x07, line ) );
  502.                         }
  503.                     else
  504.                         do    {
  505.  
  506.                             char_at( X_INFO + 2, Y_INFO, CTEOL, TEXT_COLOR );
  507.                             write_at( X_INFO + 2, Y_INFO, "Return to roll: ", TEXT_COLOR );
  508.                             gets( line, 79 );
  509.  
  510.                             } while ( ! pre_command( line, &owned, value, side, me, &winner,
  511.                                          &die_1, &die_2, c_black, c_white ) );
  512.  
  513.                     if ( winner != NOBODY )
  514.                         return( winner );
  515.  
  516.                     roll( &die_1, &die_2, &column );
  517.                     if ( die_1 == die_2 )
  518.                         sprintf( temp, "%cWhite rolls double %d's", CTEOL, die_1 );
  519.                     else
  520.                         sprintf( temp, "%cWhite rolls a %d and a %d", CTEOL, die_1, die_2 );
  521.                     write_at( X_INFO, Y_INFO, temp, TEXT_COLOR );
  522.  
  523.                     } /* first play */
  524.  
  525.                 w_movegen( die_1, die_2, FALSE, &biggest, line, FALSE );
  526.  
  527.                 if ( biggest )
  528.                     {
  529.  
  530.                     if ( c_white )
  531.                         {
  532.  
  533.                         if ( first_play )
  534.                             first( die_1, die_2, WHITE, line );
  535.                         else
  536.                             w_movegen( die_1, die_2, TRUE, &biggest, line, FALSE );
  537.  
  538.                         sprintf( temp, " and moves %s", line );
  539.                         write_at( X_INFO, column, temp, TEXT_COLOR );
  540.                         if ( ! handle_command( die_1, die_2, line, biggest, side ) )
  541.                             exit( printf( "%cplay: panic: computer move %s\n", 0x07, line ) );
  542.  
  543.                         } /* computer move */
  544.                     else
  545.                         do    {
  546.  
  547.                             char_at( X_INFO + 2, Y_INFO, CTEOL, TEXT_COLOR );
  548.                             write_at( X_INFO + 2, Y_INFO, "Your move: ", TEXT_COLOR );
  549.                             gets( line, 79 );
  550.  
  551.                             } while ( ! handle_command( die_1, die_2, line, biggest, side ) );
  552.  
  553.  
  554.                     } /* can move */
  555.                 else
  556.                     write_at( X_INFO, column, " and can not move.", ALERT_COLOR );
  557.  
  558.                 } /* can move */
  559.             else
  560.                 {
  561.                 char_at( X_INFO, Y_INFO, CTEOL, TEXT_COLOR );
  562.                 write_at( X_INFO, Y_INFO, "White can not play.", ALERT_COLOR );
  563.                 }
  564.  
  565.             } /* white */
  566.  
  567.         first_play = FALSE;
  568.  
  569.         /* do we have a winner?        */
  570.  
  571.         for( b_count = 0, i = B_BAR; i < 25; i++ )
  572.             b_count += board[ i ][ BLACK ];
  573.  
  574.         if ( ! b_count )
  575.             return( BLACK );
  576.  
  577.         for( w_count = 0, i = W_BAR; i; i-- )
  578.             w_count += board[ i ][ WHITE ];
  579.  
  580.         if ( ! w_count )
  581.             return( WHITE );
  582.  
  583.         /* swap players, and re-roll the dice */
  584.         me = ( me == WHITE ? BLACK : WHITE );
  585.  
  586.         } /* while true */
  587.  
  588.     } /* play */
  589.  
  590. /*P*/
  591. /****************************************************************/
  592. /*                                */
  593. /* first                            */
  594. /*                                */
  595. /* This routine looks up the best first move for a given    */
  596. /* player. The first roll in backgammon generally has an    */
  597. /* accepted "best" thing to do. After that, it's up to the    */
  598. /* algorithm and eval.                        */
  599. /*                                */
  600. /****************************************************************/
  601.  
  602. first( d1, d2, who, buf )
  603.  
  604. int    d1, d2, who;
  605. char    *buf;
  606.  
  607.     {
  608.  
  609.     int        temp, i;
  610.     struct        {
  611.             int    hi, low;
  612.             char    *move[ 2 ];
  613.             }    tbl[ 21 ];
  614.  
  615.     /* I hate having to do this at runtime. Anyway, this is a    */
  616.     /* table of best "first moves" given two rolls of the dice.    */
  617.     /* There are 21 possible unique combinations. This REALLY needs    */
  618.     /* to be fixed in the BDS compiler.                */
  619.  
  620.     tbl[ 0 ].hi = 6; tbl[ 0 ].low = 5;
  621.     tbl[ 0 ].move[ BLACK ] = "1/6/5";
  622.     tbl[ 0 ].move[ WHITE ] = "24/6/5";
  623.  
  624.     tbl[ 1 ].hi = 6; tbl[ 1 ].low = 4;
  625.     tbl[ 1 ].move[ BLACK ] = "1/6/4"; 
  626.     tbl[ 1 ].move[ WHITE ] = "24/6/4";
  627.  
  628.     tbl[ 2 ].hi = 6; tbl[ 2 ].low = 3;
  629.     tbl[ 2 ].move[ BLACK ] = "1/6 12/3"; 
  630.     tbl[ 2 ].move[ WHITE ] = "24/6 13/3";
  631.  
  632.     tbl[ 3 ].hi = 6; tbl[ 3 ].low = 2;
  633.     tbl[ 3 ].move[ BLACK ] = "1/6 12/2"; 
  634.     tbl[ 3 ].move[ WHITE ] = "24/6 13/2";
  635.  
  636.     tbl[ 4 ].hi = 6; tbl[ 4 ].low = 1;
  637.     tbl[ 4 ].move[ BLACK ] = "12/6 17/1"; 
  638.     tbl[ 4 ].move[ WHITE ] = "13/6 8/1";
  639.  
  640.     tbl[ 5 ].hi = 5; tbl[ 5 ].low = 4;
  641.     tbl[ 5 ].move[ BLACK ] = "12/5 12/4"; 
  642.     tbl[ 5 ].move[ WHITE ] = "13/5 13/4";
  643.  
  644.     tbl[ 6 ].hi = 5; tbl[ 6 ].low = 3;
  645.     tbl[ 6 ].move[ BLACK ] = "19/3 17/5"; 
  646.     tbl[ 6 ].move[ WHITE ] = "6/3 8/5";
  647.  
  648.     tbl[ 7 ].hi = 5; tbl[ 7 ].low = 2;
  649.     tbl[ 7 ].move[ BLACK ] = "12/5 12/2"; 
  650.     tbl[ 7 ].move[ WHITE ] = "13/5 13/2";
  651.  
  652.     tbl[ 8 ].hi = 5; tbl[ 8 ].low = 1;
  653.     tbl[ 8 ].move[ BLACK ] = "1/1 12/5"; 
  654.     tbl[ 8 ].move[ WHITE ] = "24/1 13/5";
  655.  
  656.     tbl[ 9 ].hi = 4; tbl[ 9 ].low = 3;
  657.     tbl[ 9 ].move[ BLACK ] = "12/4 12/3"; 
  658.     tbl[ 9 ].move[ WHITE ] = "13/4 13/3";
  659.  
  660.     tbl[ 10 ].hi = 4; tbl[ 10 ].low = 2;
  661.     tbl[ 10 ].move[ BLACK ] = "19/2 17/4"; 
  662.     tbl[ 10 ].move[ WHITE ] = "6/2 8/4";
  663.  
  664.     tbl[ 11 ].hi = 4; tbl[ 11 ].low = 1;
  665.     tbl[ 11 ].move[ BLACK ] = "12/4 1/1"; 
  666.     tbl[ 11 ].move[ WHITE ] = "13/4 24/1";
  667.  
  668.     tbl[ 12 ].hi = 3; tbl[ 12 ].low = 2;
  669.     tbl[ 12 ].move[ BLACK ] = "12/3 12/2"; 
  670.     tbl[ 12 ].move[ WHITE ] = "13/3 13/2";
  671.  
  672.     tbl[ 13 ].hi = 3; tbl[ 13 ].low = 1;
  673.     tbl[ 13 ].move[ BLACK ] = "19/1 17/3"; 
  674.     tbl[ 13 ].move[ WHITE ] = "6/1 8/3";
  675.  
  676.     tbl[ 14 ].hi = 2; tbl[ 14 ].low = 1;
  677.     tbl[ 14 ].move[ BLACK ] = "12/2 1/1"; 
  678.     tbl[ 14 ].move[ WHITE ] = "13/2 24/1";
  679.  
  680.     tbl[ 15 ].hi = 6; tbl[ 15 ].low = 6;
  681.     tbl[ 15 ].move[ BLACK ] = "12/6 12/6 1/6 1/6"; 
  682.     tbl[ 15 ].move[ WHITE ] = "13/6 13/6 24/6 24/6";
  683.  
  684.     tbl[ 16 ].hi = 5; tbl[ 16 ].low = 5;
  685.     tbl[ 16 ].move[ BLACK ] = "12/5/5 12/5/5"; 
  686.     tbl[ 16 ].move[ WHITE ] = "13/5/5 13/5/5";
  687.  
  688.     tbl[ 17 ].hi = 4; tbl[ 17 ].low = 4;
  689.     tbl[ 17 ].move[ BLACK ] = "1/4 1/4 12/4 12/4"; 
  690.     tbl[ 17 ].move[ WHITE ] = "24/4 24/4 13/4 13/4";
  691.  
  692.     tbl[ 18 ].hi = 3; tbl[ 18 ].low = 3;
  693.     tbl[ 18 ].move[ BLACK ] = "19/3 19/3 17/3 17/3"; 
  694.     tbl[ 18 ].move[ WHITE ] = "6/3 6/3 8/3 8/3";
  695.  
  696.     tbl[ 19 ].hi = 2; tbl[ 19 ].low = 2;
  697.     tbl[ 19 ].move[ BLACK ] = "12/2 12/2 19/2 19/2"; 
  698.     tbl[ 19 ].move[ WHITE ] = "13/2 13/2 6/2 6/2";
  699.  
  700.     tbl[ 20 ].hi = 1; tbl[ 20 ].low = 1;
  701.     tbl[ 20 ].move[ BLACK ] = "19/1 19/1 17/1 17/1"; 
  702.     tbl[ 20 ].move[ WHITE ] = "6/1 6/1 8/1 8/1";
  703.  
  704.     /* Now FINALLY we can get something done.    */
  705.  
  706.     if ( d1 < d2 )
  707.         {
  708.         temp = d1; d1 = d2; d2 = temp;
  709.         }
  710.  
  711.     for( i = 0; i < 21; i++ )
  712.         if ( ( tbl[ i ].hi == d1  ) &&
  713.              ( tbl[ i ].low == d2 ) )
  714.             {
  715.             strcpy( buf, tbl[ i ].move[ who ] );
  716.             break;
  717.             }
  718.  
  719.     if ( i == 21 )
  720.         exit( printf( "first: panic: die %d, %d who %d", d1, d2, who ) );
  721.  
  722.     } /* first */
  723.  
  724. /*P*/
  725. /****************************************************************/
  726. /*                                */
  727. /* pre_command                            */
  728. /*                                */
  729. /* Handle special commands in here. These include quitting and    */
  730. /* doubling. This section also handles the debug commands.    */
  731. /* Since these change as requirements for info do, just look at    */
  732. /* the specifics below for more info. Note, though, that the    */
  733. /* doubling cube is "owned" - no one player is allowed to use    */
  734. /* it twice in a row. We've got ta check that.            */
  735. /*                                */
  736. /****************************************************************/
  737.  
  738. pre_command( line, owned, value, side, who, winner, die_1, die_2, c_black, c_white )
  739.  
  740. char    line[];
  741. int    *owned, *value, side, who, *winner;
  742. int    *die_1, *die_2, c_black, c_white;
  743.  
  744.     {
  745.  
  746.     char    ch, accept();
  747.     int    i, j, temp1, temp2;
  748.  
  749.     *winner = NOBODY;
  750.  
  751.     for( i = 0; line[ i ]; i++ )
  752.         line[ i ] = tolower( line[ i ] );
  753.  
  754.     /* This is the easy case - we just want to go    */
  755.     /* ahead and roll the dice.            */
  756.  
  757.     if ( ( ! strcmp( line, "roll" ) ) ||
  758.          ( ! strcmp( line, "" )    ) )
  759.              return( TRUE );
  760.  
  761.     /* Handle the quit command if the user wants    */
  762.     /* out (the boss is coming! - Bruce?)        */
  763.  
  764.     if ( ( ! strcmp( line, "q" )    ) ||
  765.          ( ! strcmp( line, "quit" ) ) )
  766.         {
  767.  
  768.         char_at( X_INFO + 2, Y_INFO, CTEOL, TEXT_COLOR );
  769.         printf( "Do you really want to quit? " );
  770.  
  771.         if ( toupper( raw_keyboard() ) == 'Y' )
  772.             {
  773.             *winner = ( who == BLACK ) ? WHITE : BLACK;
  774.             return( TRUE );
  775.             }
  776.         else
  777.             {
  778.             char_at( X_INFO + 2, Y_INFO, CTEOL, TEXT_COLOR );
  779.             printf( "Well ok then!" );
  780.             line[ 0 ] = '\0';
  781.             return( FALSE );
  782.             }
  783.  
  784.         } /* quit */
  785.  
  786.     /* Handle the doubling cube here. Only allow a    */
  787.     /* double if you own the cube right now.    */
  788.  
  789.     if ( ( ! strcmp( line, "double" ) ) ||
  790.          ( ! strcmp( line, "dbl" )    ) ||
  791.          ( ! strcmp( line, "d" )      ) )
  792.         {
  793.  
  794.         /* The cube only goes up to 64, so we    */
  795.         /* check it. (The real reason is that    */
  796.         /* it does not display right as 3    */
  797.         /* digits, but...)            */
  798.  
  799.         if ( *value == 64 )
  800.             {
  801.             write_at( X_INFO + ( who == WHITE ? 0 : 1 ), Y_INFO,
  802.                   "The doubling cube only goes up to 64.", TEXT_COLOR );
  803.             return( FALSE );
  804.             } /* 64 check */
  805.  
  806.         if ( *owned != ( ( who == BLACK ) ? WHITE : BLACK ) )
  807.             {
  808.  
  809.             if ( who == BLACK )
  810.                 {
  811.                 char_at( X_INFO + 1, Y_INFO, CTEOL, TEXT_COLOR );
  812.                 write_at( X_INFO + 1, Y_INFO, "Black doubles. Do you accept? ", TEXT_COLOR );
  813.                 if ( c_white )
  814.                     ch = accept( WHITE );
  815.                 else
  816.                     do    ch = toupper( raw_keyboard() );
  817.                         while ( ( ch != 'N' ) &&
  818.                             ( ch != 'Y' ) );
  819.                 }
  820.             else
  821.                 {
  822.                 char_at( X_INFO, Y_INFO, CTEOL, TEXT_COLOR );
  823.                 write_at( X_INFO, Y_INFO, "White doubles. Do you accept? ", TEXT_COLOR );
  824.                 if ( c_black )
  825.                     ch = accept( BLACK );
  826.                 else
  827.                     do    ch = toupper( raw_keyboard() );
  828.                         while ( ( ch != 'N' ) &&
  829.                             ( ch != 'Y' ) );
  830.                 }
  831.  
  832.             if ( ch == 'Y' )
  833.                 {
  834.                 printf( " Yes." );
  835.                 *value *= 2;
  836.                 *owned = ( who == WHITE ) ? BLACK : WHITE;
  837.                 show_cube( *owned, *value, side );
  838.                 line[ 0 ] = '\0';
  839.                 return( TRUE );
  840.                 }
  841.             else
  842.                 {
  843.                 printf( " No." );
  844.                 *winner = who;
  845.                 return( TRUE );
  846.                 }
  847.  
  848.             } /* owned */
  849.  
  850.         else
  851.             write_at( X_INFO + ( who == WHITE ? 0 : 1 ), Y_INFO,
  852.                   "You do not have control of the doubling cube.", TEXT_COLOR );
  853.  
  854.         } /* double */
  855.  
  856.     /* We check all sorts of debugging stuff here, thus    */
  857.     /* enabling the user to change the board all up, etc.    */
  858.  
  859.     if ( ! strcmp( line, "debug" ) )
  860.         {
  861.         debug = ( ++debug % 4 );
  862.         sprintf( line, "debug = %d%c", debug, CTEOL );
  863.         write_at( X_INFO, Y_INFO, line, ALERT_COLOR );
  864.         }
  865.  
  866.     if ( ! strcmp( line, "load" ) )
  867.         {
  868.  
  869.         for( i = 0; i < 26; i++ )
  870.             board[ i ][ WHITE ] = board[ i ][ BLACK ] = board[ i ][ 2 ] = 0;
  871.  
  872.         draw( side );
  873.  
  874.         while ( TRUE )
  875.             {
  876.  
  877.             sprintf( line, "%cpoint white black: ", CTEOL );
  878.             write_at( X_INFO, Y_INFO, line, ALERT_COLOR );
  879.             gets( line, 79 );
  880.             if ( ! line[ 0 ] )
  881.                 break;
  882.  
  883.             sscanf( line, "%d %d %d", &i, &temp1, &temp2 );
  884.             for( j = 0; j < temp1; j++ )
  885.                 move_piece( -1, i, WHITE, side );
  886.             for( j = 0; j < temp2; j++ )
  887.                 move_piece( -1, i, BLACK, side );
  888.  
  889.             } /* read loop */
  890.  
  891.         } /* load */
  892.  
  893.     if ( ! strncmp( line, "forceroll", 9 ) )
  894.         {
  895.         sscanf( &line[ 10 ], "%d %d", &die_1, &die_2 );
  896.         show_die( 1, die_1 );
  897.         show_die( 0, die_2 );
  898.         }
  899.  
  900.     if ( ! strcmp( line, "dump" ) )
  901.         {
  902.  
  903.         for( i = 0; i < 3; i++ )
  904.             {
  905.             char_at( 21 + i, 0, CTEOL );
  906.             for( j = 0; j < 26; j++ )
  907.                 printf( "%02d ", board[ j ][ i ] );
  908.             }
  909.  
  910.         } /* dump */
  911.                     
  912.     return( FALSE );
  913.  
  914.     } /* pre_command */
  915.  
  916. /*P*/
  917. /****************************************************************/
  918. /*                                */
  919. /* handle_command                        */
  920. /*                                */
  921. /* Take a command string from the terminal, and chop it up so    */
  922. /* that it moves the pieces around on the board. Commands have    */
  923. /* the form: "4/5 18/3" - that would move the guy at point 4    */
  924. /* 5 spaces, and the guy at 18 3 spaces. The variable        */
  925. /* "required" indicates how many moves must be made. This can    */
  926. /* range from 1 up to 4 (doubles). The player must make the    */
  927. /* right number of moves.                    */
  928. /*                                */
  929. /****************************************************************/
  930.  
  931. handle_command( die_1, die_2, line, required, side )
  932.  
  933. int    die_1, die_2;
  934. char    line[];
  935. int    required, side;
  936.  
  937.     {
  938.  
  939.     char    save[ 80 ];
  940.     char    msg[ 32 ], ch;
  941.     int    test[ SIZE ][ 3 ], s_val, d_val, temp1, temp2;
  942.     int    s_psn, l_psn, done, i, j, roll_used[ 2 ];
  943.     int    start[ 5 ], dist[ 5 ], target[ 5 ];
  944.  
  945.     s_val = d_val = 0;
  946.     s_psn = l_psn = 0;
  947.     done = FALSE;
  948.  
  949.     /* until the end of line, or a maximum    */
  950.     /* of 4 moves, do            */
  951.  
  952.     while( ( ! done     ) &&
  953.            ( s_val <= 4 ) )
  954.         {
  955.  
  956.         /* move bytes into "save" until    */
  957.         /* a slash is found, then do it    */
  958.  
  959.         if ( isdigit( line[ l_psn ] ) )
  960.             save[ s_psn++ ] = line[ l_psn ];
  961.         else
  962.             switch( tolower( line[ l_psn ] ) )
  963.                 {
  964.  
  965.                 case '/':    /* end of start area, or */
  966.                         /* second distance     */
  967.                         if ( s_val == ( d_val + 1 ) )
  968.                             {
  969.                             /* A command like "14/3/5" */
  970.  
  971.                             save[ s_psn ] = '\0';
  972.                             sscanf( save, "%d", &dist[ d_val++ ] );
  973.                             s_psn = 0;
  974.  
  975.                             if ( me == WHITE )
  976.                                 start[ s_val ] = start[ s_val - 1 ] - 
  977.                                          dist[ d_val - 1 ];
  978.                             else
  979.                                 start[ s_val ] = start[ s_val - 1 ] + 
  980.                                          dist[ d_val - 1 ];
  981.                             s_val++;
  982.  
  983.                             }
  984.  
  985.                         else
  986.                             {
  987.                             /* it is a start */
  988.                             save[ s_psn ] = '\0';
  989.                             sscanf( save, "%d", &start[ s_val++ ] );
  990.                             s_psn = 0;
  991.                             }
  992.                         break;
  993.  
  994.                 case ' ':    /* end of length spec */
  995.                         save[ s_psn ] = '\0';
  996.                         sscanf( save, "%d", &dist[ d_val++ ] );
  997.                         s_psn = 0;
  998.                         break;
  999.  
  1000.                 case '\0':    /* end of length spec,    */
  1001.                         /* and end of line.    */
  1002.                         if ( l_psn == 0 )
  1003.                             return( FALSE );
  1004.                         save[ s_psn ] = '\0';
  1005.                         sscanf( save, "%d", &dist[ d_val++ ] );
  1006.                         s_psn = 0;
  1007.                         done++;
  1008.                         break;
  1009.  
  1010.                 case 'b':    /* bar is source - note that    */
  1011.                         /* it should always be followed    */
  1012.                         /* by a slash.            */
  1013.                         start[ s_val++ ] = BAR;
  1014.                         l_psn++; /* eat '/' */
  1015.                         break;
  1016.  
  1017.                 default:    char_at( X_INFO, Y_INFO, CTEOL, TEXT_COLOR );
  1018.                         printf( "I didn't understand that!" );
  1019.                         return( FALSE );
  1020.                         break;
  1021.  
  1022.                 } /* switch */
  1023.  
  1024.         /* parser checking stuff...    */
  1025.  
  1026.         if ( debug > 3 )
  1027.             {
  1028.  
  1029.             char_at( X_INFO, Y_INFO, CTEOL, TEXT_COLOR );
  1030.             printf( "Column = %d s_val = %d d_val = %d starts = ",
  1031.                 l_psn, s_val, d_val );
  1032.             for( i = 0; i < s_val; i++ )
  1033.                 printf( "%d ", start[ i ] );
  1034.             printf( "dists = " );
  1035.             for( i = 0; i < d_val; i++ )
  1036.                 printf( "%d ", dist[ i ] );
  1037.             raw_keyboard();
  1038.  
  1039.             } /* debug */
  1040.  
  1041.         l_psn++;
  1042.  
  1043.         } /* not done */
  1044.  
  1045.     /* obviously, there should be the same number of start    */
  1046.     /* places as there are distances. If not, error!    */
  1047.  
  1048.     if ( s_val != d_val )
  1049.         {
  1050.         char_at( X_INFO, Y_INFO, CTEOL, TEXT_COLOR );
  1051.         printf( "I did not understand that!" );
  1052.         return( FALSE );
  1053.         }
  1054.  
  1055.     /* The user must supply as many moves as he/she can.    */
  1056.     /* for example, if you can make 4 moves, even if one of    */
  1057.     /* them would be a strategic disaster, you must still    */
  1058.     /* make all four of the moves.                */
  1059.  
  1060.     if ( s_val != required )
  1061.         {
  1062.         char_at( X_INFO, Y_INFO, CTEOL, TEXT_COLOR );
  1063.         printf( "You must make %d %s.", required, ( required > 1 ? "moves" : "move" ) );
  1064.         return( FALSE );
  1065.         }
  1066.  
  1067.     /* make a test copy of the current game status        */
  1068.  
  1069.     movmem( board, test, BOARD_IN_BYTES );
  1070.  
  1071.     /* Zero out the roll_used array so that we can check it    */
  1072.  
  1073.     roll_used[ 0 ] = roll_used[ 1 ] = 0;
  1074.  
  1075.     /* Compute the destinations. White moves in a negative    */
  1076.     /* direction, Black moves in a positive direction.    */
  1077.     /* Both must be within range... Source must be occupied    */
  1078.  
  1079.     for( i = 0; i < s_val; i++ )
  1080.         {
  1081.  
  1082.         /* is that really what the user rolled?    */
  1083.  
  1084.         if ( ( dist[ i ] != die_1 ) &&
  1085.              ( dist[ i ] != die_2 ) )
  1086.             {
  1087.             char_at( X_INFO, Y_INFO, CTEOL, TEXT_COLOR );
  1088.             printf( "You rolled a %d and %d, not a %d!", die_1, die_2, dist[ i ] );
  1089.             return( FALSE );
  1090.             }
  1091.         else
  1092.             {
  1093.  
  1094.             /* Ok, Sure, that's what he rolled, but    */
  1095.             /* you cant use one die twice...    */
  1096.  
  1097.             if ( dist[ i ] == die_1 )
  1098.                 roll_used[ 0 ]++;
  1099.             else
  1100.                 roll_used[ 1 ]++;
  1101.  
  1102.             if ( die_1 == die_2 )
  1103.                 j = 4;
  1104.             else
  1105.                 j = 1;
  1106.  
  1107.             if ( ( roll_used[ 0 ] > j ) ||
  1108.                  ( roll_used[ 1 ] > j ) )
  1109.                 {
  1110.  
  1111.                 char_at( X_INFO, Y_INFO, CTEOL, TEXT_COLOR );
  1112.                 printf( "You've used the roll incorrectly. Try again." );
  1113.                 return( FALSE );
  1114.  
  1115.                 } /* too many! */
  1116.  
  1117.             } /* he rolled that */
  1118.  
  1119.         /* is there a man there? */
  1120.  
  1121.         if ( ( start[ i ] >= 0  ) &&
  1122.              ( start[ i ] <= 25 ) )
  1123.             if ( ! test[ start[ i ] ][ me ] )
  1124.                 {
  1125.                 char_at( X_INFO, Y_INFO, CTEOL, TEXT_COLOR );
  1126.                 printf( "There is no %s player at %d.", NAME, start[ i ] );
  1127.                 return( FALSE );
  1128.                 }
  1129.  
  1130.         /* if that was ok, compute target and test it    */
  1131.  
  1132.         if ( me == WHITE )
  1133.             {
  1134.  
  1135.             /* if we are moving off the board, is it ok?    */
  1136.  
  1137.             if ( ( ( target[ i ] = start[ i ] - dist[ i ] ) < 1 ) &&
  1138.                  ( start[ i ] != BAR                ) )
  1139.                 if ( ! w_exit_ok( test, start[ i ], dist[ i ] ) )
  1140.                     {
  1141.                     char_at( X_INFO, Y_INFO, CTEOL, TEXT_COLOR );
  1142.                     printf( "White can not exit the board yet." );
  1143.                     return( FALSE );
  1144.                     }
  1145.             }
  1146.  
  1147.         else
  1148.             {
  1149.  
  1150.             /* same here - if going off, is it valid?    */
  1151.  
  1152.             if ( ( ( target[ i ] = start[ i ] + dist[ i ] ) > 24 ) &&
  1153.                  ( start[ i ] != BAR                 ) )
  1154.                 if ( ! b_exit_ok( test, start[ i ], dist[ i ] ) )
  1155.                     {
  1156.                     char_at( X_INFO, Y_INFO, CTEOL, TEXT_COLOR );
  1157.                     printf( "Black can not exit the board yet." );
  1158.                     return( FALSE );
  1159.                     }
  1160.             }
  1161.  
  1162.         /* do the bad guys live there?    */
  1163.  
  1164.         if ( ( target[ i ] > 0            ) &&
  1165.              ( target[ i ] < 25            ) &&
  1166.              ( test[ target[ i ] ][ OTHER ] > 1 ) )
  1167.             {
  1168.             /* too many enemies there, we can't move it */
  1169.             char_at( X_INFO, Y_INFO, CTEOL, TEXT_COLOR );
  1170.             printf( "Point %d is not occupied by %s.", target[ i ], NAME );
  1171.             return( FALSE );
  1172.             }
  1173.  
  1174.         /* are we making a move with men on the bar?    */
  1175.  
  1176.         if ( ( start[ i ] != BAR ) &&
  1177.              ( test[ BAR ][ me ] ) )
  1178.             {
  1179.             char_at( X_INFO, Y_INFO, CTEOL, TEXT_COLOR );
  1180.             printf( "You canna do that! You have players on the bar!" );
  1181.             return( FALSE );
  1182.             }
  1183.  
  1184.         /* if it passed all of these, move the guy!    */
  1185.  
  1186.         test[ start[ i ] ][ me ]--;
  1187.  
  1188.         if ( ( target[ i ] > 0  ) &&
  1189.              ( target[ i ] < 25 ) )
  1190.             {
  1191.             test[ target[ i ] ][ me ]++;
  1192.             /* did we bump somebody? */
  1193.             if ( test[ target[ i ] ][ OTHER ] )
  1194.                 test[ target[ i ] ][ OTHER ] = 0;
  1195.             }
  1196.  
  1197.         } /* checking */            
  1198.  
  1199.     /* otherwise, it is ok */
  1200.  
  1201.     for( i = 0; i < s_val; i++ )
  1202.         {
  1203.  
  1204.         /* move the old piece off first, or you    */
  1205.         /* will blank out the guy that should    */
  1206.         /* be at that position.            */
  1207.  
  1208.         if ( ( target[ i ] > 0            ) &&
  1209.              ( target[ i ] < 25            ) &&
  1210.              ( board[ target[ i ] ][ OTHER ]    ) )
  1211.             move_piece( target[ i ], OTHER_BAR, OTHER, side );
  1212.  
  1213.         move_piece( start[ i ], target[ i ], me, side );
  1214.  
  1215.         } /* move all of them. */
  1216.  
  1217.     } /* handle_command */
  1218.  
  1219. /*P*/
  1220. /****************************************************************/
  1221. /*                                */
  1222. /* can_move                            */
  1223. /*                                */
  1224. /* This routine looks at the board for special conditions - if    */
  1225. /* black has a man off, for example, but all of the points are    */
  1226. /* covered by white, then black can not even move.        */
  1227. /*                                */
  1228. /****************************************************************/
  1229.  
  1230. can_move( who )
  1231.  
  1232. int    who;
  1233.  
  1234.     {
  1235.  
  1236.     int    i;
  1237.  
  1238.     if ( who == BLACK )
  1239.         {
  1240.  
  1241.         if ( board[ B_BAR ][ BLACK ] )
  1242.             {
  1243.  
  1244.             for( i = 1; i < 7; i++ )
  1245.                 if ( board[ i ][ WHITE ] < 2 )
  1246.                     return( TRUE );
  1247.             return( FALSE );
  1248.  
  1249.             }
  1250.         }
  1251.     else
  1252.         {
  1253.  
  1254.         if ( board[ W_BAR ][ WHITE ] )
  1255.             {
  1256.  
  1257.             for( i = 24; i > 18; i-- )
  1258.                 if ( board[ i ][ BLACK ] < 2 )
  1259.                     return( TRUE );
  1260.             return( FALSE );
  1261.  
  1262.             }
  1263.         }
  1264.  
  1265.     return( TRUE );
  1266.  
  1267.     } /* can_move */
  1268.